package cn.cxq.learning.array;

import org.junit.jupiter.api.Test;

import java.util.HashSet;
import java.util.Set;

/**
 * 剑指offer
 * 扑克牌顺子
 * 时间限制：C/C++ 1秒，其他语言2秒 空间限制：C/C++ 64M，其他语言128M 热度指数：410504
 * 本题知识点： 字符串
 * 算法知识视频讲解
 * 题目描述
 * 现在有五张扑克牌，我们需要来判断一下是不是顺子。
 * 有如下规则：
 * A为1,J为11,Q为12,K为13
 * 数据中的0可以看作任意牌
 * 如果给出的五张牌能组成顺子（即这五张牌是连续的）就输出true，否则就输出false。
 * 例如：给出数据[6,0,2,0,4]
 * 中间的两个0一个看作3，一个看作5 。即：[6,3,2,5,4]
 * 这样这五张牌在[2,6]区间连续，输出true
 * 数据保证每组5个数字，每组最多含有4个零
 * 示例1
 * 输入
 * 复制
 * [0,3,2,6,4]
 * 返回值
 * 复制
 * true
 */
public class IsContinuous {

    @Test
    public void testIsContinuous() {
        System.out.println(IsContinuous(new int[]{1,3,0,5,0}));
    }

    /**
     * 思路:要顺子需两个条件:
     * 1.没有重复的牌;
     * 2.最大值和最小值的差小于5.
     * @param numbers
     * @return
     */
    public boolean IsContinuous(int[] numbers) {

        Set<Integer> cards = new HashSet<>();

        int max = Integer.MIN_VALUE;
        int min = Integer.MAX_VALUE;

        int countZero = 0;

        for (int i = 0; i < numbers.length; i++) {

            if (numbers[i] == 0) {
                countZero++;
            }else {
                if (max < numbers[i]){
                    max = numbers[i];
                }

                if (min > numbers[i]){
                    min = numbers[i];
                }

                cards.add(numbers[i]);
            }
        }
        if (cards.size() + countZero < 5) {
            return false;
        } else {
            return max - min < 5 ? true : false;
        }
    }

    //自己的拙见,从头到尾找然后从尾到头找
//    public boolean IsContinuous(int[] numbers) {
//
//        return fromMinToMax(numbers) || fromMaxToMin(numbers);
//    }
//
//    private boolean fromMaxToMin(int[] numbers) {
//        int max = Integer.MIN_VALUE;
//        int countZero = 0;
//
//        for (int i = 0; i < numbers.length; i++) {
//            if (numbers[i] == 0) {
//                countZero++;
//            } else {
//                if (numbers[i] > max) {
//                    max = numbers[i];
//                }
//            }
//        }
//
//        int min = max - 4; //最小值
//
//        max--; //最大的本来就找到了
//
//        while (min <= max) {
//
//            int findNum = 0; //统计这一轮找的牌的数量
//
//            for (int i = 0; i < numbers.length; i++) {
//                if (numbers[i]!= 0 && numbers[i] == min) {
//                    min++;
//                    findNum++;
//                }
//            }
//            if (findNum == 0) { //一张都没找到而且没癞子的话就退出
//                if (countZero == 0) {
//                    break;
//                } else {
//                    countZero--;
//                    min++;
//                }
//            }
//        }
//        if (min > max) { //开始找第六张连续的牌的话,就证明找到了
//            return true;
//        }else {
//            return false;
//        }
//    }
//
//    private boolean fromMinToMax(int[] numbers) {
//        int min = Integer.MAX_VALUE;
//        int countZero = 0;
//
//        for (int i = 0; i < numbers.length; i++) {
//            if (numbers[i] == 0) {
//                countZero++;
//            } else {
//                if (numbers[i] < min) {
//                    min = numbers[i];
//                }
//            }
//        }
//
//        int max = min + 4; //最大值
//
//        min++; //最小的本来就找到了
//
//        while (min <= max) {
//
//            int findNum = 0; //统计这一轮找的牌的数量
//
//            for (int i = 0; i < numbers.length; i++) {
//                if (numbers[i]!= 0 && numbers[i] == min) {
//                    min++;
//                    findNum++;
//                }
//            }
//            if (findNum == 0) { //一张都没找到而且没癞子的话就退出
//                if (countZero == 0) {
//                    break;
//                } else {
//                    countZero--;
//                    min++;
//                }
//            }
//        }
//
//        if (min > max) { //开始找第六张连续的牌的话,就证明找到了
//            return true;
//        }else {
//            return false;
//        }
//    }
}
